﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace l1cs.server.utils
{
    class L1Random
    {
        /** 泛用型隨機矩陣，所使用的指標 */
        private static int listint = 0;

        /** 新型泛用型，適用Int的正數範圍 */
        private static double[] ArrayDouble = new double[32767];

        static L1Random()
        {
            Random rand = new Random();
            for ( listint = 0; listint < 32767; listint++ )
            {
                ArrayDouble[listint] = rand.NextDouble();
            }
        }

        private static int getlistint()
        {
            if ( listint < 32766 )
                return ++listint;
            else
                return listint = 0;
        }

        /**
         * getByte(byte[] 容器) ：模仿Random.nextBytes(byte[]) 製作
         */
        public static void getByte( byte[] arr )
        {
            for ( int i = 0; i < arr.Length; i++ )
                arr[i] = (byte)getValue( 128 );
        }

        private static bool haveNextGaussian = false;
        private static double nextGaussian;
        /**
         * getGaussian() ：回傳 高斯分配
         */
        public static double getGaussian()
        {
            if ( haveNextGaussian )
            {
                haveNextGaussian = false;
                return nextGaussian;
            }
            else
            {
                double v1, v2, s;
                do
                {
                    v1 = 2 * ArrayDouble[getlistint()] - 1;   // between -1.0 and 1.0
                    v2 = 2 * ArrayDouble[getlistint()] - 1;   // between -1.0 and 1.0
                    s = v1 * v1 + v2 * v2;
                } while ( s >= 1 || s == 0 );
                double multiplier = Math.Sqrt( -2 * Math.Log( s ) / s );
                nextGaussian = v2 * multiplier;
                haveNextGaussian = true;
                return v1 * multiplier;
            }
        }

        /**
         * getValue() ：return between 0.0 and 1.0
         */
        private static double getValue()
        {
            return ArrayDouble[getlistint()];
        }

        /**
         *
         */
        private static double getValue( int rang )
        {
            return getValue() * rang;
        }
        private static double getValue( double rang )
        {
            return getValue() * rang;
        }

        /**
         * getInt(int 數值) 隨機值的僞靜態，速度是nextInt(int 數值) 的數倍
         * 根據呼叫的數值傳回 靜態表內加工後的數值,並採共同指標來決定傳回的依據.
         * EX:getInt(92988) => 0~92987
         *
         * @param rang - Int類型
         * @return 0 ~ (數值-1)
         */
        public static int getInt( int rang )
        {
            return (int)getValue( rang );
        }

        public static int getInt( double rang )
        {
            return (int)getValue( rang );
        }

        public static double getDouble()
        {
            return getValue();
        }

        public static double getDouble( double rang )
        {
            return getValue( rang );
        }

        /**
         * getInc(int 數值, int 輸出偏移值) 隨機值的僞靜態，速度是nextInt(int 數值) 的數倍
         * 根據呼叫的數值傳回 靜態表內加工後的數值,並採共同指標來決定傳回的依據.
         * EX:getInc(92988, 10) => (0~92987) + 10 => 10~92997
         *
         * @param rang - Int類型
         * @param increase - 修正輸出結果的範圍
         * @return 0 ~ (數值-1) + 輸出偏移值
         */
        public static int getInc( int rang, int increase )
        {
            return getInt( rang ) + increase;
        }

        public static int getInc( double rang, int increase )
        {
            return getInt( rang ) + increase;
        }

        public static double getDc( int rang, int increase )
        {
            return getValue( rang ) + increase;
        }

        public static double getDc( double rang, int increase )
        {
            return getValue( rang ) + increase;
        }
    }
}
